import { useEffect, useRef, useState } from 'react'
import moment from 'moment'
import { useStrategyBacktest, BASE_CAPITAL, useTradeMarkers } from './index'

function update (chart, data) {
}

const comment = () => {
  return (
    <div>
      检测价格整理区间（Consolidation）和突破：当价格在 pivot high/low 之间整理时标记为整理区间，突破上轨买入，突破下轨卖出。同时包含 Trend Line 30 趋势线辅助判断。
    </div>
  )
}

const DEFAULT_SWING_LEN = 2
const DEFAULT_BOX_PCT = 0.18
const DEFAULT_MIN_BOX_BARS = 3
const INTERVAL_KEY = 'trendChangeYiHaHaInterval'

// Trend Line 30 默认参数
const DEFAULT_TREND30_LENGTH = 30
const DEFAULT_TREND30_MULT = 1.0
const DEFAULT_TREND30_CALC_METHOD = 'Atr' // 'Atr', 'Stdev', 'Linreg'
const DEFAULT_TREND30_BACKPAINT = true
const DEFAULT_SHOW_TREND30 = true
const DEFAULT_SHOW_EXT = true

// Pivot High/Low 计算（类似于 TradingView 的 ta.pivothigh/low）
function calculatePivots (data, swingLen) {
  const pivotMap = new Map()
  
  // 计算每个位置的 pivot high/low
  for (let i = swingLen; i < data.length - swingLen; i++) {
    const candle = data[i]
    let isPivotHigh = true
    let isPivotLow = true
    
    // 检查 pivot high：当前 high 必须比左右各 swingLen 根K线的 high 都高
    for (let j = i - swingLen; j <= i + swingLen; j++) {
      if (j !== i && data[j].high >= candle.high) {
        isPivotHigh = false
        break
      }
    }
    
    // 检查 pivot low：当前 low 必须比左右各 swingLen 根K线的 low 都低
    for (let j = i - swingLen; j <= i + swingLen; j++) {
      if (j !== i && data[j].low <= candle.low) {
        isPivotLow = false
        break
      }
    }
    
    if (isPivotHigh || isPivotLow) {
      pivotMap.set(i, {
        pivotHigh: isPivotHigh ? candle.high : null,
        pivotLow: isPivotLow ? candle.low : null
      })
    }
  }
  
  return pivotMap
}

// 计算趋势状态
function calculateTrendState (data, swingLen = DEFAULT_SWING_LEN, boxPct = DEFAULT_BOX_PCT, minBoxBars = DEFAULT_MIN_BOX_BARS) {
  const states = []
  let trend = 'unknown'
  let boxTop = null
  let boxBot = null
  let boxStartIndex = null
  let boxCount = 0
  
  let ph = null
  let pl = null
  let phBarIndex = null
  let plBarIndex = null
  
  const pivotMap = calculatePivots(data, swingLen)
  
  for (let i = 0; i < data.length; i++) {
    const candle = data[i]
    const pivot = pivotMap.get(i)
    
    // 更新 pivot high/low（只在检测到新 pivot 时更新）
    if (pivot) {
      if (pivot.pivotHigh != null) {
        ph = pivot.pivotHigh
        phBarIndex = i
      }
      if (pivot.pivotLow != null) {
        pl = pivot.pivotLow
        plBarIndex = i
      }
    }
    
    // 初始化趋势状态
    if (trend === 'unknown' && pl != null) {
      trend = 'Down'
    }
    
    // 检测整理区间
    const inPotentialBox = ph != null && pl != null && phBarIndex > plBarIndex
    const rangeHeight = inPotentialBox ? ph - pl : null
    const rangePct = inPotentialBox && pl > 0 ? rangeHeight / pl : null
    
    if (inPotentialBox && rangePct <= boxPct) {
      if (candle.high <= ph && candle.low >= pl) {
        boxCount += 1
      } else {
        boxCount = 0
      }
    } else {
      boxCount = 0
    }
    
    const isBox = boxCount >= minBoxBars
    
    // 进入整理区间
    if (isBox && (boxTop == null || ph !== boxTop || pl !== boxBot)) {
      trend = 'Consolidation'
      boxTop = ph
      boxBot = pl
      boxStartIndex = plBarIndex
      boxCount = minBoxBars // 确保计数正确
    }
    
    // 检测突破
    let breakoutUp = false
    let breakoutDn = false
    let backInBox = false
    
    if (boxTop != null && boxBot != null && i > 0) {
      const prevCandle = data[i - 1]
      breakoutUp = candle.close > boxTop && prevCandle.close <= boxTop
      breakoutDn = candle.close < boxBot && prevCandle.close >= boxBot
      backInBox = (candle.close < boxTop && prevCandle.close >= boxTop) || 
                  (candle.close > boxBot && prevCandle.close <= boxBot)
    }
    
    // 更新趋势状态
    if (breakoutUp) {
      trend = 'UP'
      boxTop = null
      boxBot = null
      boxStartIndex = null
      boxCount = 0
    } else if (breakoutDn) {
      trend = 'DOWN'
      boxTop = null
      boxBot = null
      boxStartIndex = null
      boxCount = 0
    } else if (backInBox && boxTop != null) {
      trend = 'Return to Consolidation'
    }
    
    states.push({
      trend,
      boxTop,
      boxBot,
      boxStartIndex,
      ph,
      pl,
      phBarIndex,
      plBarIndex,
      breakoutUp,
      breakoutDn,
      isBox,
      boxCount
    })
  }
  
  return states
}

const TrendChangeYiHaHaTools = (props) => {
  const [started, setStarted] = useState(false)
  const [autoRun, setAutoRun] = useState(false)
  const [finished, setFinished] = useState(false)
  const [data, setData] = useState([])
  const [currentIndex, setCurrentIndex] = useState(0)
  const [holding, setHolding] = useState(false)
  // 从 localStorage 读取参数（与指标参数同步）
  const [swingLen, setSwingLen] = useState(() => {
    try {
      const storedParams = typeof window !== 'undefined' ? localStorage.getItem('extraIndicators_params') : null
      if (storedParams) {
        const parsed = JSON.parse(storedParams)
        if (parsed?.trendChange?.swingLen != null) {
          return Number(parsed.trendChange.swingLen)
        }
      }
    } catch (e) {}
    return DEFAULT_SWING_LEN
  })
  const [boxPct, setBoxPct] = useState(() => {
    try {
      const storedParams = typeof window !== 'undefined' ? localStorage.getItem('extraIndicators_params') : null
      if (storedParams) {
        const parsed = JSON.parse(storedParams)
        if (parsed?.trendChange?.boxPct != null) {
          // 参数是百分比形式（18.0），需要转换为小数（0.18）
          const val = Number(parsed.trendChange.boxPct)
          return val > 1 ? val / 100 : val
        }
      }
    } catch (e) {}
    return DEFAULT_BOX_PCT
  })
  const [minBoxBars, setMinBoxBars] = useState(() => {
    try {
      const storedParams = typeof window !== 'undefined' ? localStorage.getItem('extraIndicators_params') : null
      if (storedParams) {
        const parsed = JSON.parse(storedParams)
        if (parsed?.trendChange?.minBoxBars != null) {
          return Number(parsed.trendChange.minBoxBars)
        }
      }
    } catch (e) {}
    return DEFAULT_MIN_BOX_BARS
  })
  
  // 监听指标参数变化（从 localStorage 同步）- 在回测开始前和回测过程中都要同步
  useEffect(() => {
    const syncParams = () => {
      try {
        const storedParams = typeof window !== 'undefined' ? localStorage.getItem('extraIndicators_params') : null
        if (storedParams) {
          const parsed = JSON.parse(storedParams)
          if (parsed?.trendChange) {
            if (parsed.trendChange.swingLen != null) {
              const newSwingLen = Number(parsed.trendChange.swingLen)
              if (newSwingLen !== swingLen) {
                setSwingLen(newSwingLen)
              }
            }
            if (parsed.trendChange.boxPct != null) {
              const val = Number(parsed.trendChange.boxPct)
              const newBoxPct = val > 1 ? val / 100 : val
              if (Math.abs(newBoxPct - boxPct) > 0.001) {
                setBoxPct(newBoxPct)
              }
            }
            if (parsed.trendChange.minBoxBars != null) {
              const newMinBoxBars = Number(parsed.trendChange.minBoxBars)
              if (newMinBoxBars !== minBoxBars) {
                setMinBoxBars(newMinBoxBars)
              }
            }
          }
        }
      } catch (e) {}
    }
    
    // 初始同步
    syncParams()
    
    // 监听 localStorage 变化（当指标参数在首页更新时）
    const handleStorageChange = (e) => {
      if (e.key === 'extraIndicators_params') {
        syncParams()
      }
    }
    window.addEventListener('storage', handleStorageChange)
    
    // 轮询检查（因为同页面的 localStorage.setItem 不会触发 storage 事件）
    const interval = setInterval(syncParams, 300)
    
    return () => {
      window.removeEventListener('storage', handleStorageChange)
      clearInterval(interval)
    }
  }, [swingLen, boxPct, minBoxBars])
  const [intervalMs, setIntervalMs] = useState(() => {
    if (typeof window !== 'undefined') {
      const stored = localStorage.getItem(INTERVAL_KEY)
      if (stored) {
        const val = Number(stored)
        if (!Number.isNaN(val) && val >= 100 && val <= 5000) {
          return val
        }
      }
    }
    return 500
  })
  const intervalRef = useRef(intervalMs)
  const autoTimerRef = useRef(null)
  const tradeInfoRef = useRef({
    active: false,
    entryPrice: 0,
    entryIndex: -1,
    overlayId: null
  })
  const overlaysRef = useRef([]) // 用于存储趋势相关的 overlay（线条、label）
  const { addTradeMarker, redrawTradeMarkers, clearTradeMarkers } = useTradeMarkers(props.chart)
  const boxOverlaysRef = useRef([]) // 用于存储所有历史 box，不清除
  const boxInfoMapRef = useRef(new Map()) // 存储 boxStartIndex -> boxId 的映射
  const boxOverlayRef = useRef(null) // 当前活跃的 box（兼容旧代码）
  const labelOverlayRef = useRef(null)
  const trend30OverlaysRef = useRef([]) // 用于存储 Trend Line 30 相关的 overlay
  const trend30LinesRef = useRef({ upper: [], lower: [] }) // 存储趋势线点
  const {
    equityHistory,
    recordEquity,
    registerTrade,
    reset: resetBacktest,
    finalize,
    SummaryModal
  } = useStrategyBacktest()

  // 将 equityHistory 传递给父组件
  useEffect(() => {
    if (props.onEquityHistoryChange) {
      props.onEquityHistoryChange(equityHistory)
    }
  }, [equityHistory])

  useEffect(() => {
    return () => {
      if (autoTimerRef.current) {
        clearInterval(autoTimerRef.current)
      }
    }
  }, [])

  useEffect(() => {
    intervalRef.current = intervalMs
    if (typeof window !== 'undefined') {
      localStorage.setItem(INTERVAL_KEY, String(intervalMs))
    }
  }, [intervalMs])

  useEffect(() => {
    if (autoTimerRef.current) {
      clearInterval(autoTimerRef.current)
    }
    if (started && autoRun && !finished) {
      autoTimerRef.current = setInterval(() => {
        nextStep()
      }, intervalRef.current)
    }
    return () => {
      if (autoTimerRef.current) {
        clearInterval(autoTimerRef.current)
      }
    }
  }, [autoRun, started, finished, data, currentIndex])

  const removeOverlay = (id) => {
    if (id && props.chart?.current) {
      try {
        props.chart.current.removeOverlay(id)
      } catch (e) {}
    }
  }

  const clearAllOverlays = () => {
    if (props.chart?.current) {
      overlaysRef.current.forEach(id => {
        try {
          props.chart.current.removeOverlay(id)
        } catch (e) {
          // ignore
        }
      })
      // 清除所有 box
      boxOverlaysRef.current.forEach(id => {
        try {
          props.chart.current.removeOverlay(id)
        } catch (e) {
          // ignore
        }
      })
      // 清除 Trend Line 30
      trend30OverlaysRef.current.forEach(id => {
        try {
          props.chart.current.removeOverlay(id)
        } catch (e) {
          // ignore
        }
      })
    }
    overlaysRef.current = []
    boxOverlaysRef.current = []
    boxInfoMapRef.current.clear() // 清除 box 信息映射
    trend30OverlaysRef.current = []
    clearTradeMarkers() // 清除买卖标记
    removeOverlay(boxOverlayRef.current)
    removeOverlay(labelOverlayRef.current)
    boxOverlayRef.current = null
    labelOverlayRef.current = null
    removeTradeOverlay()
  }

  const removeTradeOverlay = () => {
    if (tradeInfoRef.current.overlayId && props.chart?.current) {
      try {
        props.chart.current.removeOverlay(tradeInfoRef.current.overlayId)
      } catch (e) {
        // ignore
      }
    }
    tradeInfoRef.current.overlayId = null
  }

  // 使用统一的买卖标记管理器，addTradeMarker、redrawTradeMarkers、clearTradeMarkers 已从 useTradeMarkers 获取

  const refreshTradeOverlay = (actualData) => {
    const info = tradeInfoRef.current
    if (!info.active || !props.chart?.current) {
      removeTradeOverlay()
      return
    }
    if (info.entryIndex < 0 || info.entryIndex >= actualData.length) {
      removeTradeOverlay()
      return
    }
    const segment = actualData.slice(info.entryIndex)
    if (!segment.length) {
      removeTradeOverlay()
      return
    }
    // 使用全部数据的最高价和最低价
    const maxHigh = Math.max(...actualData.map(bar => bar.high))
    const minLow = Math.min(...actualData.map(bar => bar.low))
    const latestClose = segment[segment.length - 1].close
    const color = latestClose >= info.entryPrice ? 'rgba(255,22,22,0.15)' : 'rgba(13,190,28,0.15)'
    removeTradeOverlay()
    info.overlayId = props.chart.current.createOverlay({
      name: 'rect',
      styles: {
        polygon: { color }
      },
      points: [
        { timestamp: segment[0].timestamp, value: maxHigh },
        { timestamp: segment[segment.length - 1].timestamp, value: minLow }
      ]
    })
  }

  const loadRandomDataset = async () => {
    if (!props.getKlines || !props.dates) return
    const stocks = (props.stocks ?? []).filter(stock => 
      stock.open && 
      !stock.name.includes('ST')
    )
    if (!stocks.length) return
    const randomStock = stocks[Math.floor(Math.random() * stocks.length)]
    let dates = (props.dates ?? []).filter(date => {
      return date / 1000 >= randomStock.open && moment.unix(date / 1000).year() <= 2021
    })
    if (!dates.length) return
    const randomDate = dates[Math.floor(Math.random() * dates.length)]
    const dailyData = await props.getKlines(randomStock.code, '1d', randomDate, 600)
    if (!dailyData || !dailyData.length) return
    const startIndex = Math.min(Math.floor(dailyData.length / 2), dailyData.length - 1)
    const initialData = dailyData.slice(0, startIndex)
    setData(dailyData)
    setCurrentIndex(startIndex)
    setFinished(false)
    setHolding(false)
    resetBacktest()
    clearAllOverlays()
    tradeInfoRef.current = {
      active: false,
      entryPrice: 0,
      entryIndex: -1,
      overlayId: null
    }
    if (props.trader?.reset) {
      props.trader.reset()
    }
    applyChart(initialData)
    const initialTimestamp = initialData.length ? initialData[initialData.length - 1].timestamp : Date.now()
    recordEquity(initialTimestamp, props.trader?.equity ?? BASE_CAPITAL)
    setStarted(true)
    props.setInfoDisplay(false)
  }

  const createGhostBar = (last) => {
    if (!last) return null
    return {
      open: last.close,
      close: last.close,
      high: last.close,
      low: last.close,
      volume: 0,
      amount: 0,
      timestamp: last.timestamp + 24 * 60 * 60 * 1000
    }
  }

  // 绘制趋势变化相关的图形（Box、Label、线条）
  const drawTrendOverlays = (actualData) => {
    if (!props.chart?.current || actualData.length < swingLen * 2 + 1) return
    
    // 清除之前的趋势 overlay（但不清除买卖标记和已存在的 box）
    overlaysRef.current.forEach(id => {
      try {
        props.chart.current.removeOverlay(id)
      } catch (e) {
        // ignore
      }
    })
    overlaysRef.current = []
    
    const states = calculateTrendState(actualData, swingLen, boxPct, minBoxBars)
    if (!states.length) return
    
    // 使用已存在的 boxInfoMap 来追踪已绘制的 box
    const boxInfoMap = boxInfoMapRef.current
    
    // 遍历所有状态，绘制所有历史 box
    for (let i = 0; i < states.length; i++) {
      const state = states[i]
      
      // 绘制 Box（整理区间）- 保留所有历史 box
      if (state.trend === 'Consolidation' && state.boxTop != null && state.boxBot != null && state.boxStartIndex != null) {
        // 检查是否已经绘制过这个 box
        if (!boxInfoMap.has(state.boxStartIndex)) {
          // 查找这个 box 的结束位置（当趋势改变时）
          let boxEndIndex = i
          for (let j = i + 1; j < states.length; j++) {
            const nextState = states[j]
            // 如果趋势不再是 Consolidation，或者 box 参数改变了，说明 box 结束了
            if (nextState.trend !== 'Consolidation') {
              boxEndIndex = j - 1
              break
            }
            if (nextState.boxTop !== state.boxTop || nextState.boxBot !== state.boxBot) {
              boxEndIndex = j - 1
              break
            }
          }
          // 如果 box 一直持续到最后，则结束位置为最后一个索引
          if (boxEndIndex === i && i === states.length - 1) {
            boxEndIndex = states.length - 1
          } else if (boxEndIndex === i) {
            boxEndIndex = states.length - 1 // 暂时延伸到当前
          }
          
          try {
            const startCandle = actualData[state.boxStartIndex]
            const endCandle = actualData[Math.min(boxEndIndex, actualData.length - 1)]
            
            const boxId = props.chart.current.createOverlay({
              name: 'rect',
              styles: {
                polygon: {
                  color: 'rgba(255, 165, 0, 0.1)', // 黄色半透明
                  borderColor: 'rgba(255, 165, 0, 0.8)', // 橙色边框
                  borderSize: 1
                }
              },
              points: [
                { timestamp: startCandle.timestamp, value: state.boxTop },
                { timestamp: endCandle.timestamp, value: state.boxTop },
                { timestamp: endCandle.timestamp, value: state.boxBot },
                { timestamp: startCandle.timestamp, value: state.boxBot }
              ]
            })
            if (boxId) {
              boxOverlaysRef.current.push(boxId)
              boxInfoMap.set(state.boxStartIndex, boxId) // 记录 boxStartIndex -> boxId 的映射
              // 如果是当前活跃的 box，也更新 boxOverlayRef
              if (i === states.length - 1) {
                boxOverlayRef.current = boxId
              }
            }
          } catch (e) {
            console.warn('Failed to create box overlay:', e)
          }
        } else {
          // Box 已存在，如果是当前状态，更新 boxOverlayRef
          if (i === states.length - 1) {
            boxOverlayRef.current = boxInfoMap.get(state.boxStartIndex)
          }
        }
      }
    }
    
    const latestState = states[states.length - 1]
    const latestCandle = actualData[actualData.length - 1]
    
    // 绘制 Box Top/Bottom 线条（橙色十字线）
    if (latestState.boxTop != null) {
      try {
        const topLineId = props.chart.current.createOverlay({
          name: 'straightLine',
          points: [
            { timestamp: actualData[Math.max(0, actualData.length - 50)].timestamp, value: latestState.boxTop },
            { timestamp: latestCandle.timestamp, value: latestState.boxTop }
          ],
          styles: {
            line: {
              color: '#ff8800', // 橙色
              size: 1,
              style: 'dashed'
            }
          }
        })
        if (topLineId) overlaysRef.current.push(topLineId)
      } catch (e) {
        console.warn('Failed to create box top line:', e)
      }
    }
    
    if (latestState.boxBot != null) {
      try {
        const botLineId = props.chart.current.createOverlay({
          name: 'straightLine',
          points: [
            { timestamp: actualData[Math.max(0, actualData.length - 50)].timestamp, value: latestState.boxBot },
            { timestamp: latestCandle.timestamp, value: latestState.boxBot }
          ],
          styles: {
            line: {
              color: '#ff8800', // 橙色
              size: 1,
              style: 'dashed'
            }
          }
        })
        if (botLineId) overlaysRef.current.push(botLineId)
      } catch (e) {
        console.warn('Failed to create box bottom line:', e)
      }
    }
    
    // 绘制 Label（显示趋势状态）
    try {
      removeOverlay(labelOverlayRef.current)
      
      const bgColor = latestState.trend === 'DOWN' ? 'rgba(255, 0, 0, 0.8)' :
                      latestState.trend === 'Consolidation' || latestState.trend === 'Return to Consolidation' ? 'rgba(255, 255, 0, 0.8)' :
                      latestState.trend === 'UP' ? 'rgba(0, 255, 0, 0.8)' : 'rgba(128, 128, 128, 0.8)'
      
      const labelText = `${latestState.trend}\nPrice: ${latestCandle.close.toFixed(2)}`
      
      labelOverlayRef.current = props.chart.current.createOverlay({
        name: 'simpleAnnotation',
        extendData: labelText,
        points: [{ timestamp: latestCandle.timestamp, value: latestCandle.high }],
        styles: {
          annotation: {
            text: {
              color: '#000000',
              backgroundColor: bgColor,
              borderColor: bgColor
            }
          }
        }
      })
    } catch (e) {
      console.warn('Failed to create label overlay:', e)
    }
    
    // 绘制 Trend Line 30（如果启用）
    if (DEFAULT_SHOW_TREND30) {
      drawTrendLine30(actualData)
    }
  }
  
  // 计算 ATR
  const calculateATR = (data, period = 30) => {
    if (data.length < period + 1) return 0
    let sum = 0
    for (let i = data.length - period; i < data.length; i++) {
      if (i === 0) continue
      const prev = data[i - 1]
      const curr = data[i]
      const tr = Math.max(
        curr.high - curr.low,
        Math.abs(curr.high - prev.close),
        Math.abs(curr.low - prev.close)
      )
      sum += tr
    }
    return sum / period
  }
  
  // 计算标准差
  const calculateStdDev = (data, period = 30) => {
    if (data.length < period) return 0
    const slice = data.slice(data.length - period)
    const closes = slice.map(d => d.close)
    const mean = closes.reduce((a, b) => a + b, 0) / closes.length
    const variance = closes.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / closes.length
    return Math.sqrt(variance)
  }
  
  // 绘制 Trend Line 30
  const drawTrendLine30 = (actualData) => {
    if (!props.chart?.current || actualData.length < DEFAULT_TREND30_LENGTH * 2) {
      // 数据不足，不绘制
      return
    }
    
    // 清除之前的 Trend Line 30 overlay
    trend30OverlaysRef.current.forEach(id => {
      try {
        props.chart.current.removeOverlay(id)
      } catch (e) {
        // ignore
      }
    })
    trend30OverlaysRef.current = []
    
    const length30 = DEFAULT_TREND30_LENGTH
    const mult30 = DEFAULT_TREND30_MULT
    const calcMethod = DEFAULT_TREND30_CALC_METHOD
    const backpaint = DEFAULT_TREND30_BACKPAINT
    
    // 计算 pivot high/low（30周期）- 注意：calculatePivots 返回的索引是相对于数据的索引
    // TradingView 的 ta.pivothigh/low(high, 30, 30) 会在第 i 根K线时返回 i-30 位置的 pivot
    const pivotMap30 = new Map()
    
    // 重新计算 30 周期的 pivot（与 TradingView 逻辑一致）
    for (let i = length30; i < actualData.length - length30; i++) {
      const candle = actualData[i]
      let isPivotHigh = true
      let isPivotLow = true
      
      // 检查 pivot high
      for (let j = i - length30; j <= i + length30; j++) {
        if (j !== i && actualData[j].high >= candle.high) {
          isPivotHigh = false
          break
        }
      }
      
      // 检查 pivot low
      for (let j = i - length30; j <= i + length30; j++) {
        if (j !== i && actualData[j].low <= candle.low) {
          isPivotLow = false
          break
        }
      }
      
      if (isPivotHigh || isPivotLow) {
        pivotMap30.set(i, {
          pivotHigh: isPivotHigh ? candle.high : null,
          pivotLow: isPivotLow ? candle.low : null
        })
      }
    }
    
    let slopePh30 = 0
    let slopePl30 = 0
    let upper30 = 0
    let lower30 = 0
    let lastPh30 = null
    let lastPl30 = null
    let lastPhIndex = -1
    let lastPlIndex = -1
    
    // 计算 slope（简化版，主要使用 ATR）
    let slope30 = 0
    if (calcMethod === 'Atr') {
      slope30 = calculateATR(actualData, length30) / length30 * mult30
    } else if (calcMethod === 'Stdev') {
      slope30 = calculateStdDev(actualData, length30) / length30 * mult30
    } else {
      slope30 = calculateATR(actualData, length30) / length30 * mult30 // Linreg 暂时用 ATR 代替
    }
    
    let prevUpos30 = 0
    let prevDnos30 = 0
    
    // 存储每个 pivot 段的起始和结束信息
    const upperSegments = [] // { startIndex, startValue, endIndex, endValue }
    const lowerSegments = []
    let prevUpperPhIndex = -1
    let prevUpperPhValue = null
    let prevLowerPlIndex = -1
    let prevLowerPlValue = null
    
    // 遍历所有数据，计算趋势线（按照 TradingView 逻辑）
    for (let i = 0; i < actualData.length; i++) {
      const candle = actualData[i]
      const pivot = pivotMap30.get(i) // pivot 直接对应索引 i
      
      // 更新 pivot high/low（当检测到新的 pivot 时）
      if (pivot) {
        if (pivot.pivotHigh != null) {
          // 如果有之前的 pivot high，记录上一个段
          if (prevUpperPhIndex >= 0 && prevUpperPhValue != null && i > prevUpperPhIndex) {
            const prevEndValue = backpaint ?
              (prevUpperPhValue - slopePh30 * (i - 1 - prevUpperPhIndex)) :
              (prevUpperPhValue - slopePh30 * (i - 1 - prevUpperPhIndex + length30))
            upperSegments.push({
              startIndex: prevUpperPhIndex,
              startValue: prevUpperPhValue,
              endIndex: i - 1,
              endValue: prevEndValue
            })
          }
          prevUpperPhIndex = i
          prevUpperPhValue = pivot.pivotHigh
          lastPh30 = pivot.pivotHigh
          lastPhIndex = i
          slopePh30 = slope30
          upper30 = lastPh30
          prevUpos30 = 0
        }
        if (pivot.pivotLow != null) {
          // 如果有之前的 pivot low，记录上一个段
          if (prevLowerPlIndex >= 0 && prevLowerPlValue != null && i > prevLowerPlIndex) {
            const prevEndValue = backpaint ?
              (prevLowerPlValue + slopePl30 * (i - 1 - prevLowerPlIndex)) :
              (prevLowerPlValue + slopePl30 * (i - 1 - prevLowerPlIndex + length30))
            lowerSegments.push({
              startIndex: prevLowerPlIndex,
              startValue: prevLowerPlValue,
              endIndex: i - 1,
              endValue: prevEndValue
            })
          }
          prevLowerPlIndex = i
          prevLowerPlValue = pivot.pivotLow
          lastPl30 = pivot.pivotLow
          lastPlIndex = i
          slopePl30 = slope30
          lower30 = lastPl30
          prevDnos30 = 0
        }
      }
      
      // 更新 upper/lower（按照 TradingView 逻辑：如果没有新的 pivot，按 slope 递减/递增）
      if (lastPh30 != null) {
        if (i === lastPhIndex) {
          // 当前是 pivot 点，使用 pivot 值
          upper30 = lastPh30
        } else if (i > lastPhIndex) {
          // 在 pivot 之后，按 slope 递减
          const barsSincePh = i - lastPhIndex
          upper30 = lastPh30 - slopePh30 * barsSincePh
        }
      }
      
      if (lastPl30 != null) {
        if (i === lastPlIndex) {
          // 当前是 pivot 点，使用 pivot 值
          lower30 = lastPl30
        } else if (i > lastPlIndex) {
          // 在 pivot 之后，按 slope 递增
          const barsSincePl = i - lastPlIndex
          lower30 = lastPl30 + slopePl30 * barsSincePl
        }
      }
      
      // 检测突破（只在最后一个位置）
      if (i === actualData.length - 1) {
        if (lastPh30 != null) {
          const upperValue = backpaint ? upper30 : (upper30 - slopePh30 * length30)
          const upos30 = candle.close > upperValue ? 1 : 0
          if (upos30 > prevUpos30) {
            // 绘制 "B" 标记
            try {
              const markerId = props.chart.current.createOverlay({
                name: 'simpleAnnotation',
                extendData: 'B',
                points: [{ timestamp: candle.timestamp, value: candle.low }],
                styles: {
                  annotation: {
                    text: {
                      color: 'black',
                      backgroundColor: '#00ffbb', // teal
                      borderColor: '#00ffbb',
                      size: 'small'
                    }
                  }
                }
              })
              if (markerId) trend30OverlaysRef.current.push(markerId)
            } catch (e) {
              console.warn('Failed to create Trend30 upper break marker:', e)
            }
          }
          prevUpos30 = upos30
        }
        
        if (lastPl30 != null) {
          const lowerValue = backpaint ? lower30 : (lower30 + slopePl30 * length30)
          const dnos30 = candle.close < lowerValue ? 1 : 0
          if (dnos30 > prevDnos30) {
            // 绘制 "S" 标记
            try {
              const markerId = props.chart.current.createOverlay({
                name: 'simpleAnnotation',
                extendData: 'S',
                points: [{ timestamp: candle.timestamp, value: candle.high }],
                styles: {
                  annotation: {
                    text: {
                      color: 'black',
                      backgroundColor: '#ff0000', // red
                      borderColor: '#ff0000',
                      size: 'small'
                    }
                  }
                }
              })
              if (markerId) trend30OverlaysRef.current.push(markerId)
            } catch (e) {
              console.warn('Failed to create Trend30 lower break marker:', e)
            }
          }
          prevDnos30 = dnos30
        }
      }
    }
    
    // 绘制 Upper_30 线段（只在 pivot 点之间绘制，减少线条数量）
    upperSegments.forEach(segment => {
      try {
        const startCandle = actualData[segment.startIndex]
        const endCandle = actualData[segment.endIndex]
        if (startCandle && endCandle) {
          const lineId = props.chart.current.createOverlay({
            name: 'straightLine',
            points: [
              { timestamp: startCandle.timestamp, value: segment.startValue },
              { timestamp: endCandle.timestamp, value: segment.endValue }
            ],
            styles: {
              line: {
                color: '#00ffbb', // teal
                size: 1,
                style: 'solid'
              }
            }
          })
          if (lineId) trend30OverlaysRef.current.push(lineId)
        }
      } catch (e) {
        console.warn('Failed to create Trend30 upper segment:', e)
      }
    })
    
    // 绘制当前活跃的 upper 段（从最后一个 pivot 到现在）
    if (lastPh30 != null && lastPhIndex >= 0 && lastPhIndex < actualData.length - 1) {
      try {
        const startCandle = actualData[lastPhIndex]
        const endCandle = actualData[actualData.length - 1]
        if (startCandle && endCandle) {
          const endValue = backpaint ? 
            (lastPh30 - slopePh30 * (actualData.length - 1 - lastPhIndex)) :
            (lastPh30 - slopePh30 * (actualData.length - 1 - lastPhIndex + length30))
          const lineId = props.chart.current.createOverlay({
            name: 'straightLine',
            points: [
              { timestamp: startCandle.timestamp, value: lastPh30 },
              { timestamp: endCandle.timestamp, value: endValue }
            ],
            styles: {
              line: {
                color: '#00ffbb', // teal
                size: 1,
                style: 'solid'
              }
            }
          })
          if (lineId) trend30OverlaysRef.current.push(lineId)
        }
      } catch (e) {
        console.warn('Failed to create Trend30 upper active segment:', e)
      }
    }
    
    // 绘制 Lower_30 线段（只在 pivot 点之间绘制）
    lowerSegments.forEach(segment => {
      try {
        const startCandle = actualData[segment.startIndex]
        const endCandle = actualData[segment.endIndex]
        if (startCandle && endCandle) {
          const lineId = props.chart.current.createOverlay({
            name: 'straightLine',
            points: [
              { timestamp: startCandle.timestamp, value: segment.startValue },
              { timestamp: endCandle.timestamp, value: segment.endValue }
            ],
            styles: {
              line: {
                color: '#ff0000', // red
                size: 1,
                style: 'solid'
              }
            }
          })
          if (lineId) trend30OverlaysRef.current.push(lineId)
        }
      } catch (e) {
        console.warn('Failed to create Trend30 lower segment:', e)
      }
    })
    
    // 绘制当前活跃的 lower 段（从最后一个 pivot 到现在）
    if (lastPl30 != null && lastPlIndex >= 0 && lastPlIndex < actualData.length - 1) {
      try {
        const startCandle = actualData[lastPlIndex]
        const endCandle = actualData[actualData.length - 1]
        if (startCandle && endCandle) {
          const endValue = backpaint ?
            (lastPl30 + slopePl30 * (actualData.length - 1 - lastPlIndex)) :
            (lastPl30 + slopePl30 * (actualData.length - 1 - lastPlIndex + length30))
          const lineId = props.chart.current.createOverlay({
            name: 'straightLine',
            points: [
              { timestamp: startCandle.timestamp, value: lastPl30 },
              { timestamp: endCandle.timestamp, value: endValue }
            ],
            styles: {
              line: {
                color: '#ff0000', // red
                size: 1,
                style: 'solid'
              }
            }
          })
          if (lineId) trend30OverlaysRef.current.push(lineId)
        }
      } catch (e) {
        console.warn('Failed to create Trend30 lower active segment:', e)
      }
    }
    
    // 调试信息
    if (upperSegments.length > 0 || lowerSegments.length > 0 || lastPh30 != null || lastPl30 != null) {
      console.log('Trend30:', {
        dataLength: actualData.length,
        pivotMap30Size: pivotMap30.size,
        upperSegments: upperSegments.length,
        lowerSegments: lowerSegments.length,
        lastPh30,
        lastPl30
      })
    }
  }

  const applyChart = (actualData) => {
    if (!props.chart?.current) return
    if (!actualData.length) {
      props.chart.current.applyNewData([])
      props.onDataApplied?.([])
      return
    }
    const ghost = createGhostBar(actualData[actualData.length - 1])
    const chartData = ghost ? [...actualData, ghost] : [...actualData]
    
    props.chart.current.applyNewData(chartData)
    if (props.indicatorStrategies) {
      for (const indicatorStrategy of props.indicatorStrategies) {
        if (indicatorStrategy.reset) {
          indicatorStrategy.reset(props.chart.current)
        }
        indicatorStrategy.update(props.chart.current, chartData)
      }
    }
    
    // applyNewData 清除了所有 overlay，需要重新绘制
    // 绘制趋势相关图形
    drawTrendOverlays(actualData)
    
    // 重新绘制所有买卖标记
    redrawTradeMarkers()
    
    props.onDataApplied?.(chartData)
    const latest = actualData[actualData.length - 1]
    props.setPrice?.(latest.close)
  }

  const evaluateSignals = (actualData) => {
    if (actualData.length < swingLen * 2 + 2) return
    
    const states = calculateTrendState(actualData, swingLen, boxPct, minBoxBars)
    const idx = actualData.length - 1
    const prevIdx = idx - 1
    if (prevIdx < 0 || !states[idx] || !states[prevIdx]) return
    
    const state = states[idx]
    const prevState = states[prevIdx]
    const candle = actualData[idx]
    let traded = false
    
    // 记录信号检测（用于调试）
    const buySignalDetected = state.breakoutUp && prevState.trend !== 'UP'
    const sellSignalDetected = state.breakoutDn && prevState.trend !== 'DOWN'
    
    if (buySignalDetected || sellSignalDetected || state.breakoutUp || state.breakoutDn) {
      console.log('信号检测:', {
        index: idx,
        timestamp: candle.timestamp,
        price: candle.close,
        currentTrend: state.trend,
        prevTrend: prevState.trend,
        breakoutUp: state.breakoutUp,
        breakoutDn: state.breakoutDn,
        buySignalDetected,
        sellSignalDetected,
        holding,
        willBuy: buySignalDetected && !holding,
        willSell: sellSignalDetected && holding
      })
    }
    
    // 向上突破：买入
    if (buySignalDetected) {
      if (!holding) {
        props.trader.buy(candle.close)
        setHolding(true)
        addTradeMarker(candle, 'buy', candle.close)
        console.log('✅ 执行买入:', {
          price: candle.close,
          timestamp: candle.timestamp,
          index: idx,
          prevTrend: prevState.trend,
          currentTrend: state.trend
        })
        tradeInfoRef.current = {
          active: true,
          entryPrice: candle.close,
          entryTimestamp: candle.timestamp,
          entryIndex: idx,
          overlayId: tradeInfoRef.current.overlayId
        }
        traded = true
      } else {
        console.log('⚠️ 买入信号被忽略（已持仓）:', {
          price: candle.close,
          timestamp: candle.timestamp,
          index: idx
        })
      }
    }
    
    // 向下突破：卖出
    if (sellSignalDetected) {
      if (holding) {
        // 在卖出前保存成本基础，用于计算准确的收益率
        const avgCostPrice = props.trader.sell(candle.close) || tradeInfoRef.current.entryPrice || candle.close
        setHolding(false)
        addTradeMarker(candle, 'sell', candle.close)
        // tradeInfoRef.current.overlayId 是交易区间的 overlay，不需要保留到 tradeMarkers
        // 使用实际的平均成本价计算收益率
        const profitRatio = (candle.close - avgCostPrice) / avgCostPrice
        registerTrade(profitRatio, avgCostPrice, candle.close)
        console.log('✅ 执行卖出:', {
          entryPrice: tradeInfoRef.current.entryPrice,
          avgCostPrice,
          exitPrice: candle.close,
          profitRatio,
          profitPercent: (profitRatio * 100).toFixed(2) + '%',
          timestamp: candle.timestamp,
          index: idx,
          prevTrend: prevState.trend,
          currentTrend: state.trend
        })
        tradeInfoRef.current = {
          active: false,
          entryPrice: 0,
          entryTimestamp: null,
          entryIndex: -1,
          overlayId: null
        }
        traded = true
      } else {
        console.log('⚠️ 卖出信号被忽略（未持仓）:', {
          price: candle.close,
          timestamp: candle.timestamp,
          index: idx
        })
      }
    }
    
    if (traded) {
      refreshTradeOverlay(actualData)
    } else if (tradeInfoRef.current.active) {
      refreshTradeOverlay(actualData)
    }
  }

  const nextStep = () => {
    if (!started || finished || !data.length) return
    const nextIndex = Math.min(currentIndex + 1, data.length)
    if (nextIndex > data.length) return
    const actualData = data.slice(0, nextIndex)
    applyChart(actualData)
    evaluateSignals(actualData)
    const lastTimestamp = actualData.length ? actualData[actualData.length - 1].timestamp : Date.now()
    recordEquity(lastTimestamp, props.trader?.equity ?? BASE_CAPITAL)
    setCurrentIndex(nextIndex)
    if (nextIndex >= data.length) {
      // 回测结束时，如果有持仓，强制平仓并记录交易
      // 使用 tradeInfoRef.current.active 而不是 holding 状态，避免状态异步更新问题
      if (tradeInfoRef.current.active && tradeInfoRef.current.entryPrice) {
        const lastCandle = actualData[actualData.length - 1]
        if (lastCandle) {
          // 在卖出前保存成本基础，用于计算准确的收益率
          const avgCostPrice = props.trader.sell(lastCandle.close) || tradeInfoRef.current.entryPrice || lastCandle.close
          setHolding(false)
          addTradeMarker(lastCandle, 'sell', lastCandle.close)
          // 使用实际的平均成本价计算收益率
          const profitRatio = (lastCandle.close - avgCostPrice) / avgCostPrice
          registerTrade(profitRatio, avgCostPrice, lastCandle.close)
          console.log('✅ 回测结束强制平仓:', {
            entryPrice: tradeInfoRef.current.entryPrice,
            avgCostPrice,
            exitPrice: lastCandle.close,
            profitRatio,
            profitPercent: (profitRatio * 100).toFixed(2) + '%',
            timestamp: lastCandle.timestamp
          })
          tradeInfoRef.current = {
            active: false,
            entryPrice: 0,
            entryTimestamp: null,
            entryIndex: -1,
            overlayId: null
          }
          // 强制平仓后，等待状态更新再 finalize
          setTimeout(() => {
            setFinished(true)
            setAutoRun(false)
            finalize()
          }, 0)
          return // 提前返回，避免重复执行 finalize
        }
      }
      // 没有持仓，直接 finalize
      setFinished(true)
      setAutoRun(false)
      finalize()
    }
  }

  const endBacktest = () => {
    if (autoTimerRef.current) {
      clearInterval(autoTimerRef.current)
    }
    clearAllOverlays()
    window.location.reload()
  }

  const stepDisabled = !started || finished
  const autoDisabled = !started || finished

  return (
    <>
      {SummaryModal}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div style={{ display: 'flex', flexDirection: 'row', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
          {!started && (
            <button onClick={loadRandomDataset}>开始回测</button>
          )}
          {started && (
            <>
              <button disabled={stepDisabled} onClick={nextStep}>步进</button>
              <button
                disabled={autoDisabled}
                onClick={() => {
                  if (finished) return
                  setAutoRun(prev => !prev)
                }}
              >
                {autoRun ? '停止自动' : '自动'}
              </button>
              <div style={{display: 'flex', alignItems: 'center', gap: 6}}>
                <div style={{color: 'rgba(255,255,255,0.65)', fontSize: 12}}>速度</div>
                <input
                  type="range"
                  min={100}
                  max={5000}
                  step={100}
                  value={intervalMs}
                  onChange={e => setIntervalMs(Number(e.target.value))}
                  style={{width: 160}}
                />
                <div style={{minWidth: 50, textAlign: 'right', color: '#0dd697', fontSize: 12}}>{(intervalMs / 1000).toFixed(1)}s</div>
              </div>
              <button onClick={endBacktest}>结束</button>
            </>
          )}
        </div>
      </div>
    </>
  )
}

const Tools = TrendChangeYiHaHaTools

export default {
  name: '趋势变化',
  Tools,
  comment,
  update
}

